package com.googlecode.skald.server.demo;

import java.util.List;

/**
 * A user action that can be performed on a world object.
 * 
 * @author Zach Tomaszewski
 */
public enum Action {
  
  EXAMINE(1000, 1), 
  GET(2000, 1), 
  KICK(2020, 1), 
  PET(2010, 1), 
  THROW_AT(3010, 2, "Throw", "at"), 
  THROW_FOR(3020, 2, "Throw", "for"), 
  WAIT(4000, 0);
  
  private int args = 0;
  private int order;
  private String verb = null;;
  private String prep = null;
  
  /** An action and many objects it requires: 0, 1, or 2. */ 
  private Action(int order, int arity) {
    this.order = order;
    this.args = arity;
  }
  
  /** An action with the given arity (usually 2), verb, and preposition. */
  private Action(int order, int arity, String verb, String prep) {
    this(order, arity);
    this.verb = verb;
    this.prep = prep;
  }
  
  public int getArity() {
    return this.args;
  }
  
  public int getOrder() {
    return this.order;
  }
  
  /** 
   * Returns this action's verb.  If not specified, uses its name 
   * in titlecase. 
   */
  public String getVerb() {
    if (this.verb != null) {
      return this.verb;
    }else {
      return this.name().charAt(0) + this.name().substring(1).toLowerCase();
    }
  }
  
  /** 
   * Returns a JSON representation of this action given the direct and 
   * indirect objects.  These are ignored depending on the action's arity.
   * However, if the arity requires a dobj and/or iobj but the required list
   * is empty, returns an empty string, meaning this action is not currently
   * afforded.
   */
  public String toJson(List<String> dobjs, List<String> iobjs, 
                       int order, boolean weak) {
    StringBuilder affords = new StringBuilder();
    affords.append("{\"affordance\": [");
    affords.append('"' + this.getVerb() + '"');
    
    if (this.getArity() > 0) {
      if (dobjs.isEmpty()) {
        return ""; //abort: no affordances for this action
      }
      affords.append(", " + toJsonList(dobjs));
    }
    
    if (this.getArity() > 1) {
      if (iobjs.isEmpty()) {
        return ""; //no complete affordances for this action
      }
      affords.append(", \"" + this.prep + "\"");
      affords.append(", " + toJsonList(iobjs));
    }
    affords.append("]");
    affords.append(", \"order\": " + order);
    if (weak) {      
      affords.append(", \"weak\": true");
    }
    affords.append("},\n");  //no cmd for any of the demo verbs
    return affords.toString();
  }


  /** 
   * Converts the list to a comma-separate string enclosed in []s.
   */
  protected static String toJsonList(List<String> objs) {
    if (objs.isEmpty()) {
      return "[]"; 
    }
    StringBuffer str = new StringBuffer();
    str.append("[");
    String last = objs.get(objs.size() - 1);
    for (String each : objs) {
      str.append("\"");
      str.append(each);
      str.append("\"");
      if (each != last) {
        str.append(", ");  //separator
      }
    }
    str.append("]");
    return str.toString();
  }
}
